package com.iussoft.receiveData.send.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.apache.exception.BusinessException;
import com.apache.tools.DateUtils;
import com.apache.tools.StrUtil;
import com.iussoft.analyze.RequestPactlManager;
import com.iussoft.analyze.utils.DataAnalyzeUtil;
import com.iussoft.manager.InterfacePlugin;
import com.iussoft.model.DataParams;
import com.iussoft.opc.plugin.OpcUAExtend;
import com.iussoft.receiveData.send.SendSearchManager;
import com.iussoft.tools.*;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 发送服务业务接口实现
 * @author: Hou Dayu
 * @date: Created in 2020/3/16
 */
@Service("sendSearchManager")
public class SendSearchManagerImpl extends SuperSearchManager implements SendSearchManager {

    /**
     * 同步数据获取方式实现方法()
     */
    public Object sendDataMsg(DataParams params){
        depositCertificate(params,1);
        JSONObject obj = null;
        String fromStr = params.getParamsToStr("interfaceInfo");
        JSONObject from = JSON.parseObject(fromStr);
        String interCode = from.getString("interfaceCode");
        try {
            //JSONObject source = sendMsgTool.getRequestMessage(params.getParamsToStr("sourceMsg"));
           // JSONObject sourceData = dataAnalyze(source,from.getString("infoId"), "'req'",params.getTraceId());
            if("1".equals(from.getString("ifTest"))){ //测试走档板数据
                return from.getString("dataTest");
            }
            obj = sendDataMsg(from,params.getParamsToStr("sourceMsg"),params);//sourceData,params);
            if(obj != null){
            }
            LoggerUtil.infoSource("traceId = {}; interfaceCode = {}; infoType = info; exeSys = receive; requestTime = {}; requestIp = {}; responseBody = {}; method = syncSendData;",params.getParamsToStr("traceId"),interCode, DateUtils.Now.fmt_yyyyMMdd_HHmmss(),params.getParamsToStr("requestUseIp"),obj == null ? "未获取结果数据" : obj.toJSONString());
        } catch (Exception e){
            LoggerUtil.warnSource("exception = {}; infoType = exception; exeSys = receive; method = sendDataMsg; traceId = {}; interfaceCode = {}; requestTime = {}; requestIp = {}; sourceMessage = {}; errorMessage = {}; level = {}",e.getClass().getSimpleName(),params.getParamsToStr("traceId"),interCode, DateUtils.Now.fmt_yyyyMMdd_HHmmss(),params.getParamsToStr("requestUseIp"),params.getParamsToStr("sourceMsg").replaceAll("\n","").replaceAll("\r","").replaceAll(";","；"),e.getMessage(),"ERROR");
            if(e instanceof BusinessException){
                throw e;
            }
        }
        return obj;
    }

    /**
     * 发送数据实现方法
     */
    public Object syncSendData(DataParams params){
        depositCertificate(params,2);
        JSONObject obj = null;
        String fromInterface = params.getParamsToStr("interfaceInfo");
        JSONObject from = new JSONObject();
        if(StrUtil.isNotNull(fromInterface)) {
            from = JSON.parseObject(fromInterface);//接口1
        } else {
            from = getInterfaceInfo(params.getParamsToStr("interfaceId"));
        }
        String interCode = from.getString("interfaceCode");
        try{
           // JSONObject source = sendMsgTool.getRequestMessage(params.getParamsToStr("sourceMsg"));
            //JSONObject sourceData = dataAnalyze(source,from.getString("infoId"), "'req'",params.getTraceId());
            if("1".equals(from.getString("ifTest"))){ //测试走档板数据
                return from.getString("dataTest");
            }
            obj = sendDataMsg(from,params.getParamsToStr("sourceMsg"),params);//sourceData,params);
            LoggerUtil.warnSource("traceId = {}; interfaceCode = {}; infoType = info; requestTime = {}; requestIp = {}; responseBody = {}; method = syncSendData;",params.getParamsToStr("traceId"),interCode, DateUtils.Now.fmt_yyyyMMdd_HHmmss(),params.getParamsToStr("requestUseIp"),obj == null ? "未获取结果数据" : obj.toJSONString());
        }catch (Exception e){
            LoggerUtil.warnSource("exception = {}; infoType = exception; method = syncSendData; traceId = {}; interfaceCode = {}; requestTime = {}; requestIp = {}; sourceMessage = {}; errorMessage = {}; level = {}",e.getClass().getSimpleName(),params.getParamsToStr("traceId"),interCode, DateUtils.Now.fmt_yyyyMMdd_HHmmss(),params.getParamsToStr("requestUseIp"),params.getParamsToStr("sourceMsg").replaceAll("\n","").replaceAll("\r","").replaceAll(";","；"),e.getMessage(),"ERROR");
        }
        return obj;
    }

    /**
     * 异步数据获取方式实现方法
     * @param params
     * @return
     */
    public Object asyncSendData(DataParams params) {
        String interfaceCode = params.getParamsToStr("interfaceCode");
        String rowkey = params.getTraceId();
        try {
            String interfaceId = params.getParamsToStr("infterfaceId");
            String traceId =  params.getParamsToStr("traceId");
            JSONObject interfaceInfo = getInterfaceInfo(interfaceId);
            //JSONObject sourceData = dataAnalyze(source,interfaceInfo.getString("infoId"), "'req'",params.getTraceId());
            if("1".equals(interfaceInfo.getString("ifTest"))){ //测试走档板数据
                return interfaceInfo.getString("dataTest");
            }
            depositCertificate(params,4);
            JSONObject obj = sendDataMsg(interfaceInfo,params.getParamsToStr("sourceMsg"),params);
            LoggerUtil.warnSource("traceId = {}; infoType = info; requestTime = {}; requestIp = {}; interfaceCode = {}; responseBody = {}; method = asyncSendData;",traceId, DateUtils.Now.fmt_yyyyMMdd_HHmmss(),params.getParamsToStr("requestUseIp"),interfaceCode,obj == null ? "未获取结果数据" : obj.toJSONString());
            String msgFormat = interfaceInfo.getString("reqMsgFormatType");
            String callbackUrl =null;
            if("json".equalsIgnoreCase(msgFormat)) {
                JSONObject source = sendMsgTool.getRequestMessage(params.getParamsToStr("sourceMsg"));
                if(source==null){
                    return null;
                }
                callbackUrl = source.getString("callbackUrl");//数据回调地址
            }
            if (StrUtil.isNotNull(callbackUrl) && null != obj) {
                JSONObject bodyJson = dataAnalyze(obj, interfaceId, "'resp'",traceId,false);
                Map ddm = new HashMap();
                for (String key : bodyJson.keySet()) {
                    DataAnalyzeUtil.getMapToHbases("", ddm, bodyJson.get(key));
                }
                String respStr = HttpService.sendHttp(callbackUrl, "post", null, ddm);
                LoggerUtil.infoSource("traceId = {}; infoType = info; requestTime = {}; requestIp = {}; interfaceCode = {}; callbackUrl = {}; responseBody = {}",traceId, DateUtils.Now.fmt_yyyyMMdd_HHmmss(),params.getParamsToStr("requestUseIp"), interfaceCode, callbackUrl, respStr);
                return respStr;
            }
        } catch (Exception e){
            LoggerUtil.error("数据发送出错",e);
            LoggerUtil.warnSource("exception = {}; infoType = exception; method = asyncSendData; traceId = {}; interfaceCode = {}; requestTime = {}; requestIp = {}; sourceMessage = {}; errorMessage = {}; level = {}",e.getClass().getSimpleName(),params.getParamsToStr("traceId"),interfaceCode, DateUtils.Now.fmt_yyyyMMdd_HHmmss(),params.getParamsToStr("requestUseIp"),params.getParamsToStr("sourceMsg").replaceAll("\n","").replaceAll("\r","").replaceAll(";","；"),e.getMessage(),"ERROR");
        } finally {
            redisManager.delObjCache(rowkey, JedisPoolFactory.DATABASE);
        }
        return null;
    }

    /**
     * 解析报文
     */
    private JSONObject dataAnalyze(Map<String,Object> sourceMap, String interfaceId, String dataType,String traceId,boolean ifrowkey){
        LoggerUtil.info("数据解析阶段开始...");
        Map<String,Object> formats = (Map)getInterfaceParams(interfaceId,dataType).get("body");
        String matchRule = "";
        String exceptionRule = "";
        Map<String,String> rules = getRuleSite(interfaceId);
        if(rules != null && StrUtil.isNotNull(rules.get("matchRule"))){//验证匹配规则
            matchRule = rules.get("matchRule");
            exceptionRule = rules.get("exceptionRule");
        }
        if(null == formats || formats.isEmpty()){
            LoggerUtil.warnSource("traceId = {}; exeSys = send; infoType = warning; errorMessage = 没有配置解析报文",traceId);
            JSONObject result = new JSONObject();
            result.putAll(sourceMap);
            return result;
        }
        String rootName = String.valueOf(sourceMap.get("rootName"));
        if(!StrUtil.isNull(rootName)){
            //说明是xml
            LoggerUtil.info("开始解析XML格式，根节点="+rootName);
            Map<String,Object> tempMap = (Map)formats.get(rootName);
            formats.clear();
            formats.putAll((Map)tempMap.get("children"));
        }
        Map<String,Object> data = new HashMap<>();
        if("02".equals(matchRule)){//是否忽略大小写
            formats = new CaseInsensitiveMap(formats);
        }
        JSONObject result = DataAnalyzeUtil.dataAnalyze(sourceMap,formats,traceId,matchRule,exceptionRule,ifrowkey);
        return result;
    }

    private JSONObject sendDataMsg(JSONObject interfaceInfo, String sourceMessage ,DataParams dParams) {
        try {
            JSONObject reqMsg = new JSONObject();
            reqMsg.put("sourceMsg",sourceMessage);
            String result = null;
            String infoCode = interfaceInfo.getString("signConfPlug");
            String decryptClass = null;
            if(StrUtil.isNotNull(infoCode)) {
                String reqMethod = StrUtil.doNull(interfaceInfo.getString("interfaceProtocol"),"");
                Object obj = SpringContextLoader.getBean(infoCode);
                if("opc".equalsIgnoreCase(reqMethod)) {
                    obj = OpcUAExtend.getIntance(unifiedDataDao);//opc插件
                }
                if(obj == null) {
                    obj = this.getSignature(infoCode);
                }
                if (null != obj) {
                    InterfacePlugin plugin = (InterfacePlugin) obj;
                    Map<String, String> params = new HashMap<>();
                    params.put("sourceMsg", sourceMessage);
                    params.put("signCode", infoCode);
                    params.put("interfaceCode", interfaceInfo.getString("interfaceCode"));
                    params.put("interfaceProtocol", interfaceInfo.getString("interfaceProtocol"));
                    params.put("interfaceUri", interfaceInfo.getString("interfaceUri"));
                    if("jdbc".equals(reqMethod.toLowerCase())) {
                        params.put("ftpUserName", interfaceInfo.getString("ftpUserName"));
                        params.put("ftpPwd", interfaceInfo.getString("ftpPwd"));
                        params.put("ftpPath", interfaceInfo.getString("ftpPath"));
                    }
                    if(dParams.getParams().containsKey("urlParams") && StrUtil.isNotNull(dParams.getParamsToStr("urlParams"))) {
                        params.put("urlParam", JSON.toJSONString(dParams.getParamsToStr("urlParams")));
                    }
                    plugin.authentication(params);
                    reqMsg.put("sourceMsg",params.get("sourceMsg"));
                    //reqMsg=JSONObject.parseObject(params.get("sourceMsg"));//.put("sourceMsg", params.get("sourceMsg"));
                    result = params.get("responseText");
                    decryptClass = params.get("responseDecrypt");
                }
            }
            if(StrUtil.isNull(result)) {
                RequestPactlManager reqPactManager = null;
                switch (interfaceInfo.getString("interfaceProtocol").toLowerCase()){
                    case "tcp":
                    case "socket":
                        reqPactManager = (RequestPactlManager)SpringContextLoader.getBean("socketPactManager");
                        break;
                    case "ftp":
                        reqPactManager = (RequestPactlManager)SpringContextLoader.getBean("ftpPactManager");
                        break;
                    case "jms":
                        reqPactManager = (RequestPactlManager)SpringContextLoader.getBean("jmsPactManager");
                        break;
                    case "webservice":
                        reqPactManager = (RequestPactlManager)SpringContextLoader.getBean("webservicePacetManager");
                        break;
                    case "jdbc":
                        reqPactManager = (RequestPactlManager)SpringContextLoader.getBean("jDBCPactManager");
                        break;
                    case "http":
                    case "https":
                    default:
                        reqPactManager = (RequestPactlManager)SpringContextLoader.getBean("httpPactManager");
                }
                result = reqPactManager.doInvoke(interfaceInfo,reqMsg, dParams.getParams());
                if(StrUtil.isNotNull(result) && StrUtil.isNotNull(decryptClass)){
                    switch (decryptClass){
                        case "ScriptEngineUtil":
                            result = ScriptEngineUtil.getInstance().decryptCreditCustoms(result);
                            break;
                    }
                }
                if (StrUtil.isNotNull(result) && "xml".equals(interfaceInfo.getString("respMsgFormatType"))) {
                    try {
                        result = JSON.toJSONString(XMLUtil.resolveXmlToMapList(result));
                    } catch (Exception e) {
                        JSONObject jsobj = new JSONObject();
                        jsobj.put("responseBody", result);
                        return jsobj;
                    }
                }
            }
            return JSON.parseObject(result);
        } catch (Exception e){
            e.printStackTrace();
            throw new BusinessException(e.getMessage());
        }
    }
}
